package com.yanzhengwu.boot.core.druid.config;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.yanzhengwu.boot.core.druid.properties.DataSourceProperties;
import com.yanzhengwu.boot.core.datasource.DynamicDataSource;
import com.yanzhengwu.boot.core.druid.properties.DynamicDataSourceProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 数据源配置类
 */
@Configuration
@ComponentScan(value = "com.yanzhengwu")
public class DynamicDataSourceConfiguration {

    @Value("${mybatis-plus.mapper-locations}")
    private String mapperLocations;

    @Resource
    private DataSourceProperties dataSourceProperties;
    @Resource
    private DynamicDataSourceProperties dynamicDataSourceProperties;


    /**
     * 设置数据源
     */
    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dynamicDataSource(@Qualifier("dynamicDataSourceProperties")DynamicDataSourceProperties dataSourceProperties) throws Exception {
        //TODO 注册多数据源
        Map<Object, Object> stringDataSourceMap = registerDataSource(dataSourceProperties);
        if (!stringDataSourceMap.containsKey("master")) {
            throw new RuntimeException("master 数据源必须存在！");
        }

        DynamicDataSource dynamicDataSource = DynamicDataSource.build();

        // 默认数据源配置 DefaultTargetDataSource
        dynamicDataSource.setDefaultTargetDataSource(stringDataSourceMap.get("master"));
        //其他数据源配置（也包含主数据源） TargetDataSources
        dynamicDataSource.setTargetDataSources(stringDataSourceMap);
        return dynamicDataSource;
    }

    public Map<Object, Object> registerDataSource(DynamicDataSourceProperties dynamicDataSourceProperties) throws Exception {
        Map<String, Object> datasource = dataSourceProperties.getDatasource();
        Map<Object, Object> resultMap = new LinkedHashMap<>();
        if (datasource.containsKey("druid")) {
            Map<String, Object> druid = (Map<String, Object>) datasource.get("druid");
            //DynamicDataSourceProperties dynamicDataSourceProperties = new DynamicDataSourceProperties();
            BeanUtil.fillBeanWithMap(druid, dynamicDataSourceProperties, false);
            for (Map.Entry<String, Object> entry : druid.entrySet()) {
                Object k = entry.getKey();
                Object v = entry.getValue();
                if (v instanceof Map) {
                    Map<String, Object> node = (Map<String, Object>) v;
                    if (node.containsKey("driverClassName") && node.containsKey("username") && node.containsKey("password")) {
                        DynamicDataSourceProperties properties = BeanUtil.fillBeanWithMap(node, dynamicDataSourceProperties, false);
                        DruidDataSource druidDataSource = properties.setDataSource(DruidDataSourceBuilder.create().build());
                        resultMap.put(k, druidDataSource);
                    }

                }

            }
        }

        return resultMap;

    }

    /**
     * TODO 没有此bean注入则使用配置文件标准格式方式设置用户和拦截，有此方法则优先使用此方法设置
     * @return
     */
    @Bean
    public ServletRegistrationBean<StatViewServlet> druidServletRegistrationBean() {
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<StatViewServlet>();
        servletRegistrationBean.setServlet(new StatViewServlet());
        //拦截前缀
        servletRegistrationBean.addUrlMappings("/druid/*");
        //白名单
        servletRegistrationBean.addInitParameter("allow", "");
        //黑名单
        servletRegistrationBean.addInitParameter("deny", "");
        //用户信息
        servletRegistrationBean.addInitParameter("loginUsername", "root");
        servletRegistrationBean.addInitParameter("loginPassword", "root");
        return servletRegistrationBean;
    }

    /**
     * 注册DruidFilter拦截
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean<WebStatFilter> druidFilterRegistrationBean() {
        FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new WebStatFilter());
        Map<String, String> initParams = new HashMap<String, String>();
        //设置忽略请求
        initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
        filterRegistrationBean.setInitParameters(initParams);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }


    /*@Bean
    public ServletRegistrationBean<Servlet> druidServletRegistrationBean() {

        // 进行 druid 监控的配置处理
        ServletRegistrationBean<Servlet> srb = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/**");
        // 白名单
        srb.addInitParameter("allow", "127.0.0.1");
        srb.addInitParameter("allow", "localhost");
        // 黑名单
        //srb.addInitParameter("deny", "192.168.31.253");
        // 用户名
        srb.addInitParameter("loginUsername", "root");
        // 密码
        srb.addInitParameter("loginPassword", "root");
        // 是否可以重置数据源
        srb.addInitParameter("resetEnable", "false");
        return srb;
    }

    @Bean
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        FilterRegistrationBean<Filter> frb = new FilterRegistrationBean<>();
        frb.setFilter(new WebStatFilter());
        // 所有请求进行监控处理
        frb.addUrlPatterns("/*");
        // 排除名单
        frb.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*");
        return frb;
    }*/

}
